/*
输入整数m和n，输出最小公倍数。但是由于m和n比较大，因此m，n已经被分解为素因子了，
为了让格式统一，最小公倍数也用素因子表示。输入先输入一个数mp，说明m有mp个素因子，
然后有mp行，每行有两个整数，用空格分开。第一个数表示素因子，第二个数表示素因子个数；
然后再输入一个数np，说明n有np个素因子。然后有np行，格式同上。输出是m和n的最小公倍数。
如果最小公倍数有多个素因子，素因子按照升序排列。输入的数据是正整数且不超过1000。
提示：1）素因子是无序的，2）素因子可能相同。但是输出的素因子必须有序，且不能重复。
输入：
3
2 2
3 1
2 3
1
2 1
输出：
2 5
3 1
Tips：样例中：m=96 ，有2个素因子，2有5个，3有1个；n=2，只有1个素因子，2有1个。最小公倍数是12。
素因子有2个,因子2个数是2，因子3个数是1.
*/

#include <iostream>
#include <map>

using namespace std;

const int MAX_VAL = 1001;

int main(void) {
    clock_t start_time=clock();


  int mp,np;
  std::map<int, int> res_map; //存放结果

  int num,count;

  //用千位以上的位数存放m的素因子的个数
  cin >> mp;
  for (int i = 0; i < mp; i++) {
    cin >> num >> count;
    if(res_map.find(num) == res_map.end())  res_map[num] = 0;
    res_map[num] += count*MAX_VAL;
  }

  //用千位以下的位数存放n中m同样具有的素因子的个数
  cin >> np;
  for (int i = 0; i < np; i++) {
    cin >> num >> count;
    if(res_map.find(num) != res_map.end())
    {
        res_map[num] = res_map[num] + count;
    }
    else
    {
        res_map[num] = count;
    }
  }

  //扫描输出结果
  map<int, int>::iterator it = res_map.begin();
  for (; it != res_map.end(); it++) {
    count =  it->second;
    if(count >= MAX_VAL)
    {
      count = count % MAX_VAL;
      if(count > it->second / MAX_VAL)
        cout << it->first<< ' '<< count << '\n';
      else
        cout << it->first<< ' '<< it->second / MAX_VAL << '\n';
    }
    else
    {
      cout << it->first<< ' '<< count << '\n';
    }
  }



  clock_t end_time=clock();
  cout<< "Running time is: "<<static_cast<double>(end_time-start_time)/CLOCKS_PER_SEC*1000<<"ms"<<endl;//输出运行时间
  return 0;
}
